#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import os
import sys
import getopt
import subprocess
from enum import Enum


usage = """使用方式：

python tpcc.py -x /devkit/Xnbox -a 2 -f props.pg
python tpcc.py -x /devkit/Xnbox -a 2 -h 127.0.0.1 -p 6666 -d ...

参数：
    -x | --xnbox      path        xnbox目录位置
    -a | --action     0|1|2       0：建库造数据，1：跑tpcc，2：建库造数据并跑tpcc。 默认 1

    下面的两种二选一，优先直接指定文件。
    -f | --file       file        tpcc 配置文件。 但不会建用户建库，得自己建。

    -h | --host       ip          数据库ip地址, 默认 127.0.0.1
    -p | --port       port        数据库端口，默认 6666
    -d | --database   dbname      数据库名字，默认 tpccdb
    -u | --user       username    用户名，默认 tpccuser
    -w | --password   pwd         用户密码，默认 
    -W | --warehouse  warehouse   数据仓数， 默认 1000
    -t | --terminals  terminals   并发数，默认 696
    -T | --time       time        时间，单位分钟，默认 10
    -r | --readonly               是否只读，不加此参数表示读写。
"""


class Action(Enum):
    BUILD = 0
    RUN = 1
    BUILD_AND_RUM = 2

    @staticmethod
    def need_build(action):
        return action == Action.BUILD or action == Action.BUILD_AND_RUM

    @staticmethod
    def need_run(action):
        return action == Action.RUN or action == Action.BUILD_AND_RUM



class Cfg(object):
    xnbox = None
    action = Action.RUN
    file = None
    host = '127.0.0.1'
    port = 6666
    database = 'tpccuser'
    user = 'tpccuser'
    password = 'QWErty@123'
    warehouse = 1000
    terminals = 696
    run_time = 10
    readonly = False

    props = None

    @staticmethod
    def init():
        argv = sys.argv[1:]
        short_options = 'x:a:f:h:p:d:u:w:W:t:T:r'
        long_options = ['xnbox=', 'action=', 'file=', 'host=', 'port=', 'user=', 'password=', 'warehouse=',
                        'terminals=', 'time=', 'readonly']
        opts, args = getopt.getopt(argv, short_options, long_options)
        if len(args) > 1:
            print('unknown param ' + args[0])
            exit(1)
        for opt, arg in opts:
            if opt in ['-x', '--xnbox']:
                Cfg.xnbox = arg
            elif opt in ['-a', '--action']:
                Cfg.action = Action(int(arg))
            elif opt in ['-f', '--file']:
                Cfg.user = arg
            elif opt in ['-i', '--ip']:
                Cfg.ip = arg
            elif opt in ['-p', '--port']:
                Cfg.port = int(arg)
            else:
                assert False
        if Cfg.oldpkg is None or Cfg.newpkg is None:
            print('缺少参数。\n', Cfg.usage)
            exit(1)


def generate_props():
    if Cfg.file is not None:
        Cfg.props = Cfg.file
        return

    template = f"""
db=postgres
driver=org.postgresql.Driver
conn=jdbc:postgresql://{Cfg.host}:{Cfg.port}/{Cfg.database}?prepareThreshold=1&batchMode=on&fetchsize=10&preparedStatementCacheSizeMiB=0&preparedStatementCacheQueries=0
user={Cfg.user}
password={Cfg.password}

warehouses={Cfg.warehouse}
loadWorkers=50

terminals={Cfg.terminals}
//To run specified transactions per terminal- runMins must equal zero
runTxnsPerTerminal=0
//To run for specified minutes- runTxnsPerTerminal must equal zero
runMins={Cfg.run_time}
//Number of total transactions per minute
limitTxnsPerMin=0

//Set to true to run in 4.x compatible mode. Set to false to use the
//entire configured database evenly.
terminalWarehouseFixed=false
"""
    if not Cfg.readonly:
        template += """
//The following five values must add up to 100
//The default percentages of 45, 43, 4, 4 & 4 match the TPC-C spec
newOrderWeight=45
paymentWeight=43
orderStatusWeight=4
deliveryWeight=4
stockLevelWeight=4
"""
    else:
        template += """
//The following five values must add up to 100
//The default percentages of 45, 43, 4, 4 & 4 match the TPC-C spec
newOrderWeight=0
paymentWeight=0
orderStatusWeight=50
deliveryWeight=0
stockLevelWeight=50 
        """


def check_tpcc_exists():
    pass


def tpcc_build():
    sql = f"create user {Cfg.user} with password \\'{Cfg.password}\\' sysadmin; create database {Cfg.database} owner {Cfg.user};"
    cmd = f"gsql -d postgres -p {Cfg.port} -c '{sql}'"



def run():
    pass


if __name__ == '__main__':
    Cfg.init()
    generate_props()

    if Action.need_build(Cfg.action):
        build()

    if Action.need_run(Cfg.action):
        run()
